﻿using System;
using System.Collections.Generic;
using WyUnity.Utility;
using WyUnity.Utility.Dynamic;
using WyUnity.Utility.ExtentionMethods;

namespace WyUnity.Data.TableMapper
{
    /// <summary>
    /// 只读数据映射对象的基础实现
    /// </summary>
    public abstract class ViewBase<T> : IView where T : ViewBase<T>
    {
        void IMapObject.LoadData(System.Data.IDataReader dataReader)
        {
            foreach (var ps in _props_set_method_cache)
            {
                var value = dataReader[ps.Key];
                try
                {
                    ps.Value(this, new object[] { value });
                }
                catch
                {
                    _log.Error("设置对象[{1}]属性[{0}]失败", ps.Key, this.GetType().Name);
                }
            }
        }

        string IMapObject.GetSQLClip(DataAccess.ISqlDialect dialect)
        {
            return string.Format("({0}) as TEMPTABLE", GetSQLClip());
        }

        public abstract string GetSQLClip();

        #region 静态初始化
        /// <summary>
        /// 对象全部属性设置方法
        /// </summary>
        private static Dictionary<string, Func<object, object[], object>> _props_set_method_cache;
        private static Logger _log = Log.Get<T>();

        static ViewBase()
        {
            _props_set_method_cache = new Dictionary<string, Func<object, object[], object>>();

            var type = typeof(T);
            var props = type.GetProperties();
            foreach (var p in props)
            {
                var atts = p.GetCustomAttributes(typeof(MapAttribute), false);
                if (atts.Length == 1)
                {
                    var mapattr = atts[0] as MapAttribute;

                    //以Map的FieldName为Key
                    var pname = mapattr.Name;
                    //如果没有设置FieldName，则已字段的名称为Key
                    if (pname.IsNullOrEmpty()) pname = p.Name;

                    if (p.CanWrite)
                    {
                        _props_set_method_cache.Add(pname, DynamicCall.GetExecuteDelegate(p.GetSetMethod()));
                    }
                }
            }
        }
        #endregion

    }
}